﻿#include <iostream>
#include <cstdio>
#include <fstream>
#include <map>
#include <Windows.h>
using namespace std;

string source;
char pred[10001];
int token_num;
int keynum = 6, numnum = 0;
map <string, int> Map;
map <int, int> numMap;

enum Keywords
{
	IF = 0, ELSE, FOR, INt, VOId, MAIN
};
string KeywordsF[] = { "IF", "ELSE", "FOR", "INT", "VOID", "MAIN" };
enum Operators
{
	PLUS = 0, MINUS, MULTI, DIVIDE, PLUSD, MINUSD, MULTID, DIVIDED, LESS, LESSE, GREATER, GREATERE, GIVEVALUE, EQUAL, NEQUAL, NOT
};
string OperatorsF[] = { "PLUS", "MINUS", "MULTI", "DIVIDE", "PLUSD", "MINUSD", "MULTID", "DIVIDED", "LESS", "LESSE", "GREATER", "GREATERE", "GIVEVALUE", "EQUAL", "NEQUAL", "NOT"};
enum Delimiters
{
	BRACEL = 0, BRACER, BRACKETL, BRACKETR, COMMA, SEMICOLON, SQUAREL, SQUARER 
};
string DelimitersF[] = { "BRACEL", "BRACER", "BRACKETL", "BRACKETR", "COMMA", "SEMICOLON", "SQUAREL", "SQUARER" };
enum Type
{
	KEYWORD = 0, OPERATOR, CONSt, IDENTIFIER, DELIMITER 
};
string TypeF[] = {"KEYWORD", "OPERATOR", "CONST", "IDENTIFIER", "DELIMITER" };

struct Token
{
	Type type;
	int value;
} token[10001];

void AddToken(Type type, int value)
{
	token[++token_num] = { type, value };
}

void SetColorAndBackground(int ForgC, int BackC) {
	WORD wColor = ((BackC & 0x0F) << 4) + (ForgC & 0x0F);
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), wColor);
}
inline bool isAlpha(char c)
{
	return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
}
inline bool isDigit(char c)
{
	return (c >= '0' && c <= '9');
}

void Init()
{
	Map["if"] = 1;
	Map["else"] = 2;
	Map["for"] = 3;
	Map["int"] = 4;
	Map["void"] = 5;
	Map["main"] = 6;
}

void ReadSource()
{
	ifstream in("main.subcpp");
	if (!in.is_open())
	{
		printf("找不到文件！");
		exit(0);
	}
	istreambuf_iterator<char> beg(in), end;
	string source1(beg, end);
	source = source1;
	printf("源文件：\n");
	std::cout << source << std::endl;
}

void InsertNumMap(int a)
{
	if (numMap[a] != 0)
	{
		AddToken(CONSt, numMap[a]);
	}
	else
	{
		numMap[a] = (++numnum);
		AddToken(CONSt, numnum);
	}
}

void Pre()
{
	int length_s = source.length();
	int length = 0;
	int pre = 1;
	int def = 0;
	for (int i = 0; i < length_s; i++)
	{
		char j = source[i];
		if (pre == 1 && j == '#') def = 1, pre = 0;
		if (pre == 1 && j != ' ' && j != 10) pre = 0;
		if (def == 1 && j == 10) 
		{
			def = 0; pre = 1;
		}
		else
		{
			if (def == 0)
			{
				pred[length++] = j;
			}
			if (j == 10) pre = 1;
		}
	}
	pred[length] = '\0';
	printf("\n删除宏定义 头文件等：\n");
	std::cout << pred << std::endl;
}

void Main()
{
	int n = strlen(pred);
	int i = 0;

	while (i < n)
	{
		if (pred[i] == ' ' || pred[i] == 10 || pred[i] == 9) { i++; continue; }
		if (pred[i] == '+')
		{
			i++;
			if (i == n)
			{
				AddToken(OPERATOR, Operators(PLUS));
				continue;
			}
			else if (pred[i] == '=')
			{
				AddToken(OPERATOR, Operators(PLUSD));
				i++;
				continue;
			}
			else 
			{
				AddToken(OPERATOR, Operators(PLUS));
				continue;
			}
		}
		else if (pred[i] == '-')
		{
			i++;
			if (i == n)
			{
				AddToken(OPERATOR, Operators(MINUS));
				continue;
			}
			else if (pred[i] == '=')
			{
				AddToken(OPERATOR, Operators(MINUSD));
				i++;
				continue;
			}
			else
			{
				AddToken(OPERATOR, Operators(MINUS));
				continue;
			}
		}
		else if (pred[i] == '*')
		{
			i++;
			if (i == n || pred[i] != '=')
			{
				AddToken(OPERATOR, Operators(MULTI));
				continue;
			}
			else if (pred[i] == '=')
			{
				AddToken(OPERATOR, Operators(MINUSD));
				i++;
				continue;
			}
		}
		else if (pred[i] == '/')
		{
			i++;
			if (i == n || pred[i] != '=')
			{
				AddToken(OPERATOR, Operators(DIVIDE));
				continue;
			}
			else if (pred[i] == '=')
			{
				AddToken(OPERATOR, Operators(DIVIDED));
				i++;
				continue;
			}
		}
		else if (pred[i] == '<')
		{
			i++;
			if (i == n || pred[i] != '=')
			{
				AddToken(OPERATOR, Operators(LESS));
				continue;
			}
			else if (pred[i] == '=')
			{
				AddToken(OPERATOR, Operators(LESSE));
				i++;
				continue;
			}
		}
		else if (pred[i] == '>')
		{
			i++;
			if (i == n || pred[i] != '=')
			{
				AddToken(OPERATOR, Operators(GREATER));
				continue;
			}
			else if (pred[i] == '=')
			{
				AddToken(OPERATOR, Operators(GREATERE));
				i++;
				continue;
			}
		}
		else if (pred[i] == '=')
		{
			i++;
			if (i == n || pred[i] != '=')
			{
				AddToken(OPERATOR, Operators(GIVEVALUE));
				continue;
			}
			else if (pred[i] == '=')
			{
				AddToken(OPERATOR, Operators(EQUAL));
				i++;
				continue;
			}
		}
		else if (pred[i] == '!')
		{
			i++;
			if (i == n || pred[i] != '=')
			{
				AddToken(OPERATOR, Operators(NOT));
				continue;
			}
			else if (pred[i] == '=')
			{
				AddToken(OPERATOR, Operators(NEQUAL));
				i++;
				continue;
			}
		}
		else if (pred[i] == '{')
		{
			i++;
			AddToken(DELIMITER, Delimiters(BRACEL));
		}
		else if (pred[i] == '}')
		{
			i++;
			AddToken(DELIMITER, Delimiters(BRACER));
		}
		else if (pred[i] == '(')
		{
			i++;
			AddToken(DELIMITER, Delimiters(BRACKETL));
		}
		else if (pred[i] == ')')
		{
			i++;
			AddToken(DELIMITER, Delimiters(BRACKETR));
		}
		else if (pred[i] == ',')
		{
			i++;
			AddToken(DELIMITER, Delimiters(COMMA));
		}
		else if (pred[i] == ';')
		{
			i++;
			AddToken(DELIMITER, Delimiters(SEMICOLON));
		}
		else if (pred[i] == '[')
		{
			i++;
			AddToken(DELIMITER, Delimiters(SQUAREL));
		}
		else if (pred[i] == ']')
		{
			i++;
			AddToken(DELIMITER, Delimiters(SQUARER));
		}
		else if (isAlpha(pred[i]))
		{
			char temp[256]; int j = 0;
			temp[j] = pred[i++];
			while (i < n && isAlpha(pred[i]) || isDigit(pred[i]))
			{
				temp[++j] = pred[i++];
			}
			temp[j + 1] = '\0';
			string temp1 = temp;
			int pos = Map[temp1];
			if (pos >= 1 && pos <= 6)
			{
				AddToken(KEYWORD, pos);
			}
			else
			{
				if (pos)
				{
					AddToken(IDENTIFIER, pos);
				}
				else
				{
					Map[temp1] = (++keynum);
					AddToken(IDENTIFIER, keynum);
				}
			}
		}
		else if (isDigit(pred[i]))
		{
			int temp = pred[i++] - '0';
			while (i < n && isDigit(pred[i]))
				temp = temp * 10 + pred[i] - '0', i++;
			InsertNumMap(temp);
		}
		else
		{
			SetColorAndBackground(7, 4);
			cout << "ERROR : 存在不能识别的符号：" << pred[i++] << endl;
		}
	}
}

void Print()
{
	SetColorAndBackground(15, 0);
	cout << "\ntoken序列输出至_Tokens.txt\n标识符表输出至_Identifiers_Table.txt\n常数表输出至_Const_Table.txt\n";
	freopen("_Tokens.txt", "w", stdout);
	for (int i = 1; i <= token_num; i++)
	{
		Token j = token[i];
		if (j.type == KEYWORD) cout << "<KEYWORD, " << KeywordsF[j.value - 1] << ">\n";
		if (j.type == IDENTIFIER) cout << "<IDENTIFIER, " << j.value - 6 << ">\n";
		if (j.type == CONSt) cout << "<CONST, " << j.value << ">\n";
		if (j.type == DELIMITER) cout << "<DELIMITER, " << DelimitersF[j.value] << ">\n";
		if (j.type == OPERATOR) cout << "<OPERATOR, " << OperatorsF[j.value] << ">\n";
	}
	freopen("_Identifiers_Table.txt", "w", stdout);
	for (map<string, int>::iterator it = Map.begin(); it != Map.end(); it++)
	{
		if (it->second > 6) cout << it->first << " " << it->second - 6 << endl;
	}
	freopen("_Const_Table.txt", "w", stdout);
	for (map<int, int>::iterator it = numMap.begin(); it != numMap.end(); it++)
	{
		cout << it->first << " " << it->second << endl;
	}
	fclose(stdout);
}

int main()
{
	Init();
	ReadSource();
	Pre();
	Main();
	Print();
}